// Classes (类) 示例
// 演示 Pascal 中类的各种用法
program p_26_classes;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式，支持面向对象编程
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils;  // 系统工具单元，包含常用的系统函数

// 定义一个简单的人员类
type
  TPerson = class
  private
    FName: String;
    FAge: Integer;
    procedure SetName(const Value: String);
    procedure SetAge(const Value: Integer);
  public
    constructor Create; overload;
    constructor Create(const AName: String; const AAge: Integer); overload;
    procedure Introduce;
    function GetInfo: String;
    property Name: String read FName write SetName;
    property Age: Integer read FAge write SetAge;
  end;

// TPerson类的实现
constructor TPerson.Create;
begin
  FName := '未知';
  FAge := 0;
end;

constructor TPerson.Create(const AName: String; const AAge: Integer);
begin
  FName := AName;
  FAge := AAge;
end;

procedure TPerson.SetName(const Value: String);
begin
  if Value <> '' then
    FName := Value
  else
    FName := '未知';
end;

procedure TPerson.SetAge(const Value: Integer);
begin
  if Value >= 0 then
    FAge := Value
  else
    FAge := 0;
end;

procedure TPerson.Introduce;
begin
  WriteLn('大家好，我是 ', FName, '，今年 ', FAge, ' 岁。');
end;

function TPerson.GetInfo: String;
begin
  Result := '姓名: ' + FName + ', 年龄: ' + IntToStr(FAge);
end;

// 定义一个学生类（继承自TPerson）
type
  TStudent = class(TPerson)
  private
    FStudentID: String;
    FScore: Real;
  public
    constructor Create(const AName: String; const AAge: Integer; const AStudentID: String); overload;
    procedure Study;
    procedure SetScore(AScore: Real);
    function GetGrade: String;
    property StudentID: String read FStudentID write FStudentID;
    property Score: Real read FScore write FScore;
  end;

// TStudent类的实现
constructor TStudent.Create(const AName: String; const AAge: Integer; const AStudentID: String);
begin
  inherited Create(AName, AAge);
  FStudentID := AStudentID;
  FScore := 0.0;
end;

procedure TStudent.Study;
begin
  WriteLn(Name, ' 正在学习...');
end;

procedure TStudent.SetScore(AScore: Real);
begin
  if (AScore >= 0) and (AScore <= 100) then
    FScore := AScore
  else
    FScore := 0;
end;

function TStudent.GetGrade: String;
begin
  if FScore >= 90 then
    Result := '优秀'
  else if FScore >= 80 then
    Result := '良好'
  else if FScore >= 70 then
    Result := '中等'
  else if FScore >= 60 then
    Result := '及格'
  else
    Result := '不及格';
end;

// 程序主入口
begin
  WriteLn('=== Pascal 类示例 ===');
  WriteLn;
  
  // 1. 创建和使用基本类对象
  WriteLn('1. 创建和使用基本类对象:');
  var person1: TPerson := TPerson.Create('张三', 25);
  try
    person1.Introduce;
    WriteLn('  人员信息: ', person1.GetInfo);
    
    // 使用属性
    person1.Name := '李四';
    person1.Age := 30;
    WriteLn('  修改后信息: ', person1.GetInfo);
  finally
    person1.Free;  // 释放对象
  end;
  
  WriteLn;
  
  // 2. 使用默认构造函数
  WriteLn('2. 使用默认构造函数:');
  var person2: TPerson := TPerson.Create;
  try
    person2.Introduce;
    person2.Name := '王五';
    person2.Age := 20;
    person2.Introduce;
  finally
    person2.Free;
  end;
  
  WriteLn;
  
  // 3. 继承类的使用
  WriteLn('3. 继承类的使用:');
  var student1: TStudent := TStudent.Create('小明', 18, '2023001');
  try
    student1.Introduce;  // 继承的方法
    student1.Study;      // 自己的方法
    
    student1.SetScore(85);
    WriteLn('  学生 ', student1.Name, ' 的成绩: ', student1.Score:0:1);
    WriteLn('  等级: ', student1.GetGrade);
  finally
    student1.Free;
  end;
  
  WriteLn;
  
  // 4. 多个对象的使用
  WriteLn('4. 多个对象的使用:');
  var people: array[1..3] of TPerson;
  
  people[1] := TPerson.Create('赵六', 22);
  people[2] := TStudent.Create('小红', 19, '2023002');
  people[3] := TPerson.Create('钱七', 24);
  
  try
    for var i := 1 to 3 do
    begin
      people[i].Introduce;
      // 检查对象类型
      if people[i] is TStudent then
        TStudent(people[i]).Study;
    end;
  finally
    // 释放所有对象
    for var i := 1 to 3 do
      people[i].Free;
  end;
  
  WriteLn;
  
  // 5. 属性访问演示
  WriteLn('5. 属性访问演示:');
  var person3: TPerson := TPerson.Create('孙八', 28);
  try
    WriteLn('  原始姓名: ', person3.Name);
    WriteLn('  原始年龄: ', person3.Age);
    
    // 通过属性设置值
    person3.Name := '';
    person3.Age := -5;
    WriteLn('  非法设置后姓名: ', person3.Name);
    WriteLn('  非法设置后年龄: ', person3.Age);
  finally
    person3.Free;
  end;
  
  WriteLn;
  WriteLn('演示了 Pascal 中类的各种用法');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.